﻿using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using AntDesign;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using SageKing.Database;

namespace SageKing.Blazor.OpenIdService.Components.Base;

public class AComponentBase : ComponentBase, IAComponentBase<AComponentBase>
{
    // 初始化一个信号量，初始计数和最大计数均为 1，表示一次只允许一个线程进入
    public readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
    public bool IsDisposed { get; set; } = false;
    public BaseRenderFragment baseRender { get; set; }

    #region 通用高参数

    /// <summary>
    ///  Header + Tab height
    /// 顶部偏移高度，默认 64 + 50 = 114
    /// </summary>
    public double TopOffset { get; set; } = (64 + 50);

    /// <summary>
    ///  分页组件高度
    /// </summary>
    public double PaginationHeight { get; set; } = 44;
    /// <summary>
    /// 滚动条高度
    /// </summary>
    public double ScrollBarHeight { get; set; } = 15;

    /// <summary>
    /// 通用工具栏高度
    /// </summary>
    public double IndexToolBarHeight { get; set; } = 36;

    /// <summary>
    /// 表格工具栏顶部高度
    /// </summary>
    public double TableToolBarHeight { get; set; } = 50;

    /// <summary>
    /// 分割条宽度
    /// </summary>
    public double SplitterWidth { get; set; } = 8;

    [CascadingParameter]
    public Error? Error { get; set; }

    #endregion

    #region 通用参数
    [Inject]
    public IIdGenerator IdGenerator { get; set; }

    [Inject]
    public AntDesign.IMessageService Message { get; set; }

    [Inject]
    public IConfirmService ConfirmService { get; set; }

    [Inject]
    public ProtectedSessionStorage ProtectedSessionStore { get; set; }

    [Inject]
    public ILogger<AComponentBase> Logger { get; set; }

    [Inject]
    public NotificationService Notice { get; set; }

    [Inject]
    public IJSRuntime Js { get; set; }

    [Inject]
    public JsCommJsInterop JsCommModule { get; set; }

    [Inject]
    public NavigationManager NavigationManager { get; set; }

    [Inject]
    public IOptions<SageKingDatabaseOptions> SageKingDatabaseOptions { get; set; }

    public Dictionary<string, JsonColumnProperties> JsonColumnDic
    {
        get
        {
            var result = SageKingDatabaseOptions?.Value?.TemplateConfigSet?.JsonColumn;
            if (result == null)
            {
                return new Dictionary<string, JsonColumnProperties>();
            }
            return result;
        }
    }
    #endregion

    #region copy

    public bool ShowManualCopy { get; set; }

    public async Task Clipboard(ElementReference btn, string copy)
    {
        await ((IAComponentBase<AComponentBase>)this).IClipboard(btn, copy);
    }

    #endregion

    #region 共用方法
    #region 动态调用

    public virtual object InvokeGenericMethod(object instance, Type targetType, string methodName, params object[] parms)
    {
        return InvokeGenericMethodViaDelegate(instance, methodName, targetType, parms);
    }

    // 缓存委托
    private static readonly ConcurrentDictionary<string, Delegate> DelegateCache = new ConcurrentDictionary<string, Delegate>();
    public object InvokeGenericMethodViaDelegate(object instance, string methodName, Type targetType, object[] parameters)
    {
        string cacheKey = $"{methodName}_{targetType.FullName}";

        // 获取或创建委托
        var del = DelegateCache.GetOrAdd(cacheKey, key =>
        {
            MethodInfo genericMethodDef = instance.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            if (genericMethodDef == null) return null;

            MethodInfo constructedMethod = genericMethodDef.MakeGenericMethod(targetType);

            // 创建委托
            // 假设方法签名是：ReturnType MethodName(TParam param)
            // 需要根据实际方法签名调整参数和返回类型
            var instanceParam = Expression.Parameter(typeof(object), "instance");
            var parametersParam = Expression.Parameter(typeof(object[]), "parameters");

            var call = Expression.Call(
                instance: Expression.Convert(instanceParam, instance.GetType()), // 转换实例
                method: constructedMethod,
                arguments: constructedMethod.GetParameters().Select((p, i) =>
                    Expression.Convert(Expression.ArrayIndex(parametersParam, Expression.Constant(i)), p.ParameterType)) // 转换参数
            );

            var lambda = Expression.Lambda(
                body: Expression.Convert(call, typeof(object)), // 转换返回值
                parameters: new[] { instanceParam, parametersParam }
            );

            return lambda.Compile(); // 编译为委托
        });

        if (del == null)
        {
            throw new ArgumentException($"Method {methodName} with type {targetType.FullName} not found.");
        }

        // 调用委托
        return ((Func<object, object[], object>)del)(instance, parameters);
    }
    #endregion
    #endregion

    #region 模板参数
    [Parameter]
    public virtual string TemplateName { get; set; }
    [Parameter]
    public virtual string TemplateType { get; set; }
    [Parameter]
    public virtual Dictionary<string, object> Properties { get; set; }
    #endregion

    protected override async Task OnInitializedAsync()
    {
        baseRender = new BaseRenderFragment();
        await base.OnInitializedAsync();
    }

    public new void StateHasChanged()
    {
        base.StateHasChanged();
    }

    #region 通用组件


    bool _dynamicValue = false;
    public virtual RenderFragment GetRenderModal<T, K>(IModal<T> modal)
      where T : IEntityBaseId<K>, new()
        => builder =>
        {
            int seq = 0;
            builder.OpenComponent<Modal>(seq++);
            builder.AddAttribute(seq++, "Title", modal.Title);
            builder.AddAttribute(seq++, "Class", modal.Class);
            builder.AddAttribute(seq++, "MaxBodyHeight", modal.MaxBodyHeight);
            builder.AddAttribute(seq++, "Width", modal.Width);
            builder.AddAttribute(seq++, "Draggable", modal.Draggable);
            builder.AddAttribute(seq++, "Centered", modal.Centered);
            builder.AddAttribute(seq++, "Closable", modal.Closable);
            builder.AddAttribute(seq++, "Visible", modal.Visible);
            builder.AddAttribute(seq++, "VisibleChanged", EventCallback.Factory.Create<bool>(this, newValue => _dynamicValue = newValue));

            builder.AddAttribute(seq++, "OnOk", EventCallback.Factory.Create<MouseEventArgs>(this, modal.HandleOk));
            builder.AddAttribute(seq++, "ConfirmLoading", modal.Loading);
            builder.AddAttribute(seq++, "OkText", modal.OkTitle);
            builder.AddAttribute(seq++, "CancelText", modal.CancelText);
            builder.AddAttribute(seq++, "OnCancel", EventCallback.Factory.Create<MouseEventArgs>(this, modal.HandleClose));

            builder.AddAttribute(seq++, "ChildContent", (RenderFragment)((builder2) =>
            {
                builder2.AddContent(seq++, modal.ModalTemplate);
            }));
            builder.CloseComponent(); // 关闭组件

        };
    #endregion

}
